
package jing.typedef.property;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

public class AllowedValueRange implements Parcelable {

    private static final String TAG = AllowedValueRange.class.getSimpleName();

    private DataType dataType;
    private Object minValue;
    private Object maxValue;

    public static AllowedValueRange create(DataType type, Object min, Object max) {
        AllowedValueRange thiz = null;

        do {
            boolean valid = false;

            if (!type.getJavaDataType().isInstance(min)) {
                Log.d(TAG, "create failed, min dataType invalid");
                break;
            }

            if (!type.getJavaDataType().isInstance(max)) {
                Log.d(TAG, "create failed, max dataType invalid");
                break;
            }

            switch (type.getType()) {
                case BOOLEAN:
                    break;

                case BYTES:
                    break;

                case DOUBLE:
                    valid = (Double) min < (Double) max;
                    break;

                case FLOAT:
                    valid = (Float) min < (Float) max;
                    break;

                case INTEGER:
                    valid = (Integer) min <= (Integer) max;
                    break;

                case LONG:
                    valid = (Long) min <= (Long) max;
                    break;

                case STRING:
                    break;

                case UNDEFINED:
                    break;

                default:
                    break;
            }

            if (!valid) {
                Log.d(TAG, "create failed, min >= max");
                break;
            }

            thiz = new AllowedValueRange();
            thiz.dataType = type;
            thiz.minValue = min;
            thiz.maxValue = max;
        } while (false);

        return thiz;
    }

    public Object getMinValue() {
        return minValue;
    }

    public Object getMaxValue() {
        return maxValue;
    }

    public boolean isValid(Object value) {
        boolean valid = false;

        do {
            if (!this.dataType.getJavaDataType().isInstance(value)) {
                Log.d(TAG, "dataType invalid");
                break;
            }

            switch (dataType.getType()) {
                case BOOLEAN:
                    break;

                case BYTES:
                    break;

                case DOUBLE:
                    valid = Double.compare((Double) value, (Double) this.minValue) >= 0
                            && Double.compare((Double) this.maxValue, (Double) value) >= 0;
//                    valid = (Double) this.minValue <= (Double) value && (Double) value <= (Double) this.maxValue;
                    break;

                case FLOAT:
                    valid = Float.compare((Float) value, (Float) this.minValue) >= 0
                            && Float.compare((Float) this.maxValue, (Float) value) >= 0;
//                    valid = (Float) this.minValue <= (Float) value && (Float) value <= (Float) this.maxValue;
                    break;

                case INTEGER:
                    valid = (Integer) this.minValue <= (Integer) value && (Integer) value <= (Integer) this.maxValue;
                    break;

                case LONG:
                    valid = (Long) this.minValue <= (Long) value && (Long) value <= (Long) this.maxValue;
                    break;

                case STRING:
                    break;

                case UNDEFINED:
                    break;

                default:
                    break;
            }
        } while (false);

        return valid;
    }

    public static final Creator<AllowedValueRange> CREATOR = new Parcelable.Creator<AllowedValueRange>() {

        @Override
        public AllowedValueRange createFromParcel(Parcel in) {
            return new AllowedValueRange(in);
        }

        @Override
        public AllowedValueRange[] newArray(int size) {
            return new AllowedValueRange[size];
        }
    };

    private AllowedValueRange() {
    }

    public AllowedValueRange(Parcel in) {
        readFromParcel(in);
    }

    public void readFromParcel(Parcel in) {
        this.dataType = in.readParcelable(DataType.class.getClassLoader());

        switch (dataType.getType()) {
            case BOOLEAN:
                break;

            case BYTES:
                break;

            case DOUBLE:
                this.minValue = in.readDouble();
                this.maxValue = in.readDouble();
                break;

            case FLOAT:
                this.minValue = in.readFloat();
                this.maxValue = in.readFloat();
                break;

            case INTEGER:
                this.minValue = in.readInt();
                this.maxValue = in.readInt();
                break;

            case LONG:
                this.minValue = in.readLong();
                this.maxValue = in.readLong();
                break;

            case STRING:
                break;

            case UNDEFINED:
                break;

            default:
                break;
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeParcelable(this.dataType, flags);

        switch (dataType.getType()) {
            case BOOLEAN:
                break;

            case BYTES:
                break;

            case DOUBLE:
                out.writeDouble((Double) this.minValue);
                out.writeDouble((Double) this.maxValue);
                break;

            case FLOAT:
                out.writeFloat((Float) this.minValue);
                out.writeFloat((Float) this.maxValue);
                break;

            case INTEGER:
                out.writeInt((Integer) this.minValue);
                out.writeInt((Integer) this.maxValue);
                break;

            case LONG:
                out.writeLong((Long) this.minValue);
                out.writeLong((Long) this.maxValue);
                break;

            case STRING:
                break;

            case UNDEFINED:
                break;

            default:
                break;
        }
    }
}